package xyz.syyrjx.provider;

import lombok.Data;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import xyz.syyrjx.provider.conf.SyyrjxRpcProviderConfiguration;
import xyz.syyrjx.provider.task.SyyrjxRpcProviderSchedule;
import xyz.syyrjx.provider.util.SyyrjxRpcProviderHeartClientStartUtil;
import xyz.syyrjx.request.SyyrjxRpcRegistryRequest;
import xyz.syyrjx.client.SyyrjxRpcClient;
import xyz.syyrjx.provider.annotation.SyyrjxRpcProvider;
import xyz.syyrjx.provider.exception.SyyrjxRpcProviderException;
import xyz.syyrjx.entity.SyyrjxRpcServicesTable;
import xyz.syyrjx.provider.handler.SyyrjxRpcProviderServerHandler;
import xyz.syyrjx.initializer.SyyrjxRpcChannelInitializer;
import xyz.syyrjx.server.SyyrjxRpcServer;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 大地崩坏苍蝇兽
 * @date 2023/1/6 - 17:47
 */
@Data
public class SyyrjxRpcProviderClass {

    private final static Logger LOGGER = LoggerFactory.getLogger(SyyrjxRpcProviderClass.class);


    private final static String CLASS_FILE_SUFFIX = ".class";

    private final static String CLASS_SEPARATOR = ".";

    private final static Class TARGET_ANNOTATION = SyyrjxRpcProvider.class;

    @Getter
    private Map<String, Map<String, SyyrjxRpcServicesTable>> providerMap = null;

    /**
     * 创建提供者-服务表
     * @param applicationContext applicationContext
     */
    public void createProviderMap(ApplicationContext applicationContext) {
        if (providerMap != null){
            return;
        }
        providerMap = new HashMap<>();
        Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(SyyrjxRpcProvider.class);
        for (Map.Entry<String, Object> providerEntry : beansWithAnnotation.entrySet()) {
            //提供者接口实现获取
            Object provider = providerEntry.getValue();
            SyyrjxRpcProvider providerAnnotation = provider.getClass().getAnnotation(SyyrjxRpcProvider.class);
            String providerName = providerAnnotation.value();
            Class<?> prviderClass = provider.getClass();
            Class<?> idClass = prviderClass.getInterfaces()[0];

            providerName = "".equals(providerName) ? idClass.getName() : providerName;
            if (providerMap.containsKey(providerName)) {
                throw new SyyrjxRpcProviderException(SyyrjxRpcProviderException.PROVIDER_NAME_REDEFINE);
            }
            providerMap.put(providerName, new HashMap<>());
            Map<String, SyyrjxRpcServicesTable> servicesMap = providerMap.get(providerName);
            Method[] methods = idClass.getMethods();
            //服务（提供者方法）获取
            for (Method method : methods) {
                String serviceName = method.getName();
                if (servicesMap.containsKey(serviceName)) {
                    throw new SyyrjxRpcProviderException(SyyrjxRpcProviderException.SERVICE_NAME_REDEFINE);
                }
                SyyrjxRpcServicesTable service = new SyyrjxRpcServicesTable();
                service.setBean(provider);
                service.setClazz(prviderClass);
                service.setMethod(method);
                servicesMap.put(serviceName, service);
            }
        }
        LOGGER.debug("提供者构建服务表完成：" + providerMap);
    }


    /**
     * 启动提供者服务器
     */
    public void providerServerRun() {
        SyyrjxRpcProviderServerHandler handler = new SyyrjxRpcProviderServerHandler();
        handler.setProvider(this);
        SyyrjxRpcChannelInitializer channelInitializer = new SyyrjxRpcChannelInitializer();
        channelInitializer.setHandler(handler);
        channelInitializer.setMaxReadSize(SyyrjxRpcProviderConfiguration.getConfiguration().getMaxReadSize());
        new SyyrjxRpcServer(SyyrjxRpcProviderConfiguration.getConfiguration().getPort()).run(channelInitializer);
    }

    /**
     * 启动客户端，发送注册消息
     * @throws InterruptedException throws
     */
    public void providerClientRun(SyyrjxRpcProviderSchedule schedule) throws InterruptedException {
        SyyrjxRpcClient providerClient = new SyyrjxRpcClient();
        SyyrjxRpcProviderHeartClientStartUtil.start(providerClient);

        SyyrjxRpcRegistryRequest request = new SyyrjxRpcRegistryRequest();

        LOGGER.debug("提供者表：" + providerMap.toString());
        String[] providerNames = new String[providerMap.size()];
        int index = 0;
        for (String providerName : providerMap.keySet()) {
            LOGGER.debug(providerName);
            providerNames[index++]= providerName;
        }
        request.setAddress(SyyrjxRpcProviderConfiguration.getLocal());
        request.setProviderNames(providerNames);

        schedule.setClient(providerClient);
        schedule.run(request);
        LOGGER.debug("创建心跳定时任务成功");
    }

}
